package com.offics.loan.domain.service;

import com.offics.loan.domain.entity.Loan;
import com.offics.loan.domain.entity.RepaymentPlan;
import com.offics.loan.domain.entity.RepaymentRecord;
import com.offics.loan.domain.repository.LoanRepository;
import com.offics.loan.domain.repository.RepaymentPlanRepository;
import com.offics.loan.domain.repository.RepaymentRecordRepository;
import com.offics.loan.domain.repository.UserRepository;
import com.offics.loan.infrastructure.exception.BusinessException;
import com.offics.loan.infrastructure.common.ResultCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 还款领域服务
 */
@Service
@RequiredArgsConstructor
public class RepaymentDomainService {

    private final RepaymentPlanRepository repaymentPlanRepository;
    private final RepaymentRecordRepository repaymentRecordRepository;
    private final LoanRepository loanRepository;
    private final UserRepository userRepository;

    /**
     * 还款
     *
     * @param userId          用户ID
     * @param loanId          贷款ID
     * @param repaymentPlanId 还款计划ID
     * @param amount          还款金额
     * @param repayType       还款方式
     * @param bankCardId      银行卡ID
     * @return 还款记录
     */
    @Transactional(rollbackFor = Exception.class)
    public RepaymentRecord repay(Long userId, Long loanId, Long repaymentPlanId, Long amount, Integer repayType, Long bankCardId) {
        // 检查用户是否存在
        userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));

        // 检查贷款是否存在
        Loan loan = loanRepository.findById(loanId)
                .orElseThrow(() -> new BusinessException(ResultCode.LOAN_NOT_FOUND));

        // 检查贷款是否属于该用户
        if (!loan.getUserId().equals(userId)) {
            throw new BusinessException(ResultCode.LOAN_NOT_BELONG_TO_USER);
        }

        // 检查贷款是否已经放款
        if (!loan.isLoanIssued()) {
            throw new BusinessException(ResultCode.LOAN_NOT_ISSUED);
        }

        // 检查还款计划是否存在
        RepaymentPlan repaymentPlan = repaymentPlanRepository.findById(repaymentPlanId)
                .orElseThrow(() -> new BusinessException(ResultCode.REPAYMENT_PLAN_NOT_FOUND));

        // 检查还款计划是否属于该贷款
        if (!repaymentPlan.getLoanId().equals(loanId)) {
            throw new BusinessException(ResultCode.REPAYMENT_PLAN_NOT_BELONG_TO_LOAN);
        }

        // 检查还款计划是否可以还款
        if (!repaymentPlan.canRepay()) {
            throw new BusinessException(ResultCode.REPAYMENT_PLAN_CANNOT_REPAY);
        }

        // 检查还款金额是否正确
        if (!amount.equals(repaymentPlan.getAmount())) {
            throw new BusinessException(ResultCode.REPAYMENT_AMOUNT_ERROR);
        }

        // 创建还款记录
        RepaymentRecord repaymentRecord = new RepaymentRecord();
        repaymentRecord.setLoanId(loanId);
        repaymentRecord.setRepaymentPlanId(repaymentPlanId);
        repaymentRecord.setUserId(userId);
        repaymentRecord.setAmount(amount);
        repaymentRecord.setRepayTime(LocalDateTime.now());
        repaymentRecord.setRepayType(repayType);
        repaymentRecord.setBankCardId(bankCardId);
        repaymentRecord.setTradeNo(repaymentRecordRepository.generateTradeNo());
        repaymentRecord.setStatus(1); // 成功

        // 更新还款计划状态
        repaymentPlan.setStatus(1); // 已还
        repaymentPlan.setActualRepayTime(LocalDateTime.now());
        repaymentPlanRepository.update(repaymentPlan);

        // 检查贷款是否已经结清
        boolean allPaid = true;
        List<RepaymentPlan> repaymentPlans = repaymentPlanRepository.findByLoanId(loanId);
        for (RepaymentPlan plan : repaymentPlans) {
            if (!plan.isPaid()) {
                allPaid = false;
                break;
            }
        }

        // 如果所有还款计划都已还款，则更新贷款状态为已结清
        if (allPaid) {
            loan.setStatus(6); // 已结清
            loan.setRepayEndTime(LocalDateTime.now());
            loanRepository.update(loan);
        } else {
            // 如果贷款状态为已逾期，则更新为还款中
            if (loan.isOverdue()) {
                loan.setStatus(5); // 还款中
                loanRepository.update(loan);
            }
        }

        // 保存还款记录
        return repaymentRecordRepository.saveAndReturn(repaymentRecord);
    }

    /**
     * 查询用户的还款计划
     *
     * @param userId 用户ID
     * @return 还款计划列表
     */
    public List<RepaymentPlan> getUserRepaymentPlans(Long userId) {
        // 检查用户是否存在
        userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));

        return repaymentPlanRepository.findByUserId(userId);
    }

    /**
     * 查询贷款的还款计划
     *
     * @param loanId 贷款ID
     * @return 还款计划列表
     */
    public List<RepaymentPlan> getLoanRepaymentPlans(Long loanId) {
        // 检查贷款是否存在
        loanRepository.findById(loanId)
                .orElseThrow(() -> new BusinessException(ResultCode.LOAN_NOT_FOUND));

        return repaymentPlanRepository.findByLoanId(loanId);
    }

    /**
     * 查询用户的还款记录
     *
     * @param userId 用户ID
     * @return 还款记录列表
     */
    public List<RepaymentRecord> getUserRepaymentRecords(Long userId) {
        // 检查用户是否存在
        userRepository.findById(userId)
                .orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));

        return repaymentRecordRepository.findByUserId(userId);
    }

    /**
     * 查询贷款的还款记录
     *
     * @param loanId 贷款ID
     * @return 还款记录列表
     */
    public List<RepaymentRecord> getLoanRepaymentRecords(Long loanId) {
        // 检查贷款是否存在
        loanRepository.findById(loanId)
                .orElseThrow(() -> new BusinessException(ResultCode.LOAN_NOT_FOUND));

        return repaymentRecordRepository.findByLoanId(loanId);
    }
}